// The MIT License (MIT)
// © mihakralj
//@version=6
indicator("Triple Exponential Moving Average (TEMA)", "TEMA", overlay=true)

//@function Calculates TEMA using triple exponential smoothing with compensator
//@param source Series to calculate TEMA from
//@param alpha smoothing factor 
//@param corrected Using traditional or diminishing alpha factors
//@returns TEMA value from first bar with proper compensation
//@optimized for performance and dirty data
tema(series float source, int period = 0, float alpha = 0.0, bool corrected = false) =>
    if alpha <= 0 and period <= 0
        runtime.error("Alpha or period must be provided")
    float a1 = alpha > 0 ? alpha : (period > 0 ? 2.0/(period+1) : 0.1)
    float r = math.pow(1/a1, 1/3)
    float a2 = corrected ? a1*r : a1, float a3 = corrected ? a2*r : a1

    float d1 = 1-a1, float d2 = 1-a2, float d3 = 1-a3
    var float e1 = 1.0, var float e2 = 1.0, var float e3 = 1.0
    var bool warmup = true, float result = na

    var float rema1 = 0, var float rema2 = 0, var float rema3 = 0
    var float ema1 = source, var float ema2 = source, var float ema3 = source
    rema1 := a1*(source - rema1) + rema1
    if warmup
        e1 *= d1, e2 *= d2, e3 *= d3
        float c1 = 1.0/(1.0-e1), float c2 = 1.0/(1.0-e2), float c3 = 1.0/(1.0-e3)
        ema1 := rema1 * c1
        rema2 := a2*(ema1 - rema2) + rema2
        ema2 := rema2 * c2
        rema3 := a3*(ema2 - rema3) + rema3
        ema3 := rema3 * c3
        warmup := e1<=1e-10 ? false : true
    else
        ema1 := rema1
        rema2 := a2*(ema1 - rema2) + rema2
        ema2 := rema2
        rema3 := a3*(ema2 - rema3) + rema3
        ema3 := rema3
    3*ema1-3*ema2+ema3


// ---------- Main loop ----------

// Inputs
i_period = input.int(10, "Period", minval=1)
i_source = input.source(close, "Source")

// Calculation
tema = tema(i_source, period=i_period, corrected = true)
tema_traditional = tema(i_source, period=i_period)

// Plot
plot(tema, "TEMA", color.new(color.yellow, 0), 2)
plot(tema_traditional, "TEMA", color.new(color.orange, 0), 1)

